var newTask = new Object(); //预定义新任务类
var contacts;               //存储所有联系人，供选择人员快速调用，通过ajax返回的json数据生成
var taskList;               //当前页所有任务的列表，通过ajax返回的json数据加载
var lastTaskTitle;          //最后一次新建任务的标题，主要用以防止多次重复操作
var lastSubTaskTitle;       //最后一次新建子任务的标题，功能同上
var us;                     //预定义的用户选择器treeview。
var lastFeedback;           //最后一次反馈内容，防止多次重复误提交


//加载任务列表视图
function loadTaskList() {
    $.ajax({ cache: false });
    $("#page-wrapper").load("parts/parts.tasklist.html");
}


//任务列表的快速完成checkbox的点击事件
function checkboxClicked(chkbox) {
    var row = $('#taskListTable').DataTable().row($("#" + chkbox.id).data('rowid')).data();
    //checkbox选定时的操作，将任务置为完成度100%，并刷新列表中的行。
    if (chkbox.checked) {
        setCompletion(row.task.id, 1000, function (data) {
            if (data.status == 0) {
                row.task.completion = data.entity.completion;
                $('#taskListTable').DataTable().row($("#" + chkbox.id).data('rowid')).data(row).draw();
            }
            else (chkbox.checked = false);
        }, function (status, err) {
            warn(status + "\n" + err);
        });
    //未选定时的操作，将任务完成度恢复原来的进度
    } else {
        setCompletion(row.task.id, -1, function (data) {
            if (data.status == 0) {
                row.task.completion = data.entity.completion;
                $('#taskListTable').DataTable().row($("#" + chkbox.id).data('rowid')).data(row).draw();
            }
            else (chkbox.checked = true);
        }, function (status, err) {
            warn(status + "\n" + err);
        });
    }
}

//通过ajax设置任务的完成度
//参数：
//    tId:任务的ID
//    comp:要设置的任务完成度
//    callback:ajax请求成功后（不等于操作成功）的回调方法
//    errCallback:ajax请求失败后的回调方法
function setCompletion(tId, comp, callback, errCallback) {
    op = createOperation('setCompletion', { taskId: tId, completion: comp });
    getJson(op, function (data) {
        if (callback) callback(data);
    }, function (status, err) {
        if (errCallback) errCallback(status, err);
    });
}


//JS功能执行入口
$(document).ready(function () {
    //获取联系人数据,异步方式
    var op = createOperation('getContacts');
    getJson(op, function (data) {
        if (data.status == 0) {
            contacts = data.entity;
            us = new userSelector('treeview-checkable', contacts);      //新建userSelector实体
            us.setData(contacts);                                       //初始化userSelector数据
            us.setUserTree('treeview-checkable');                       //传递DOM对象名到userSelector
            us.onNodeSelected = function (event, node) {                //定义节点被选中时的回调方法
                $("#targetUserName").html(node.text);
                newTask.implementId = node.id;
                $("#userbook").hide();
            }
            us.onNodeUnselected = function (event, node) {              //定义节点取消选中时的回调方法
                $("#targetUserName").html("");
                delete newTask.implementId;
                $("#userbook").hide();
            }
            us.show();                                                  //show方法，使userSelector渲染DOM（非显示，取决于DOM是否可见）
        }
        else warn(data.message);
    }, function (status, err) {
        warn("数据请求失败：\nStatus:" + status + "\nerror:" + err);     //warn方法目前仅实现alert，后期更改为模态弹窗
    });

    getTaskList();  //获取任务列表，异步方式


    //加载datetimepicker组件，并初始化，以替代HTML巨丑的date input效果，并支持IE
    $(".form_datetime").datetimepicker({
        language: 'zh-CN',
        format: "yyyy-mm-dd",
        weekStart: 1,
        todayBtn: 1,
        autoclose: 1,
        todayHighlight: 1,
        startView: 2,
        minView: 2,
        forceParse: 0,
        showMeridian: 1
    });
    //设置datetimepicker的数值变化回调方法
    $(".form_datetime").on("changeDate", function (ev) {
        $("#dateValue").html(new DateConvertor(ev.date).toShortDate());
    });

    //设置添加实施人按钮的click事件方法
    $("#userbook").unbind('click').click(function (e) {
        e.stopPropagation();
    });

    //通过document点击事件关闭可能存在的浮层（注意相关的e.stopPropagation阻止JS的起泡事件）
    $(document).click(function (event) {
        $("#userbook").hide();
        $("#addExeDiv").hide();
        $("#addRdrDiv").hide();
        $("#subuserbook").hide();
    });

    //定义选择执行人按钮click事件方法
    $("#targetUser").click(function (e) {
        e.stopPropagation();
        $("#userbook").show();
    });

    //定义新任务标题输入框的keypress事件方法，检测到回车后提交新任务
    $("#newTaskTitle").unbind('keypress').keypress(function (ev) {
        if (ev.keyCode == 13 || ev.key == "Enter") {
            if ($(this).val() == "") {
                return;
            }
            if ($(this).val() == lastTaskTitle) {
                warn("请勿重复创建任务！");
                $(this).val("");
                return;
            }
            newTask.title = $(this).val();
            newTask.deadLine = $("#newTaskDate").val();
            getJson(createOperation('createTask', newTask), function (data) {
                if (data.status == 0) {
                    addNewTaskNode(correctTaskItem(data.entity), $("#taskListTable").DataTable());
                    lastTaskTitle = data.entity.task.title;
                    $("#newTaskTitle").val("");
                }
                else warn(data.message);
            }, function (status, err) {
                warn("REQ STAT=" + status + "\nERR:" + err);
            });
        }
    });

    //向任务列表中的Datatables组件中添加新的任务行
    function addNewTaskNode(t, table) {
        //t = new Task from server response.
        //table = target table;
        if (!t || !table) {
            warn("new task node error. t=" + t + " table=" + table);
            return;
        }
        var rowNode = table.row.add(t).draw().node();
        table.order([5, 'desc']).draw();
        $(rowNode).css('color', 'red').animate({ color: 'black' });
    }


    //纠正ajax返回的json数据中的deadLine字段，使其符合datatables的需要
    function correctTaskItem(t) {
        if (t) {
            if (t.deadLine == undefined)
                t.deadLine = "";
        }
        return t;
    }

    //获取任务列表
    function getTaskList() {
        var op = createOperation('getTaskList',{action:taskType});
        getJson(op, function (data) {
            if (data.status == 0) {
                taskList = data.entity;
                for (var i in taskList) {
                    correctTaskItem(taskList[i].task);
                }
                showTable(taskList);
            }
        });
    }

    //显示任务列表的datatables属性
    function showTable(data) {
        $.fn.dataTable.ext.errMode = 'none';
        var taskTable = $('#taskListTable').DataTable({
            "autoWidth": false,
            "data": data,
            "columns": [{
                "data": 'task.completion',
                "width": "16px",
                "orderable": false,
                "render": function (data, type, row, meta) {
                    if (type == "display") {
                        if (row.reader) return '<span class="fa fa-search" style="color:#CCCCCC" title="分阅的任务" aria-hidden="true"></span>';
                        if (data >= 100) {
                            return '<input type="checkbox" class="myCheck" checked="checked" id="c' + row.task.id + '"' + (row.task.reader > 0 ? ' disabled' : '') + ' onclick="checkboxClicked(this)" data-rowid="' + meta.row + '"><label for="c' + row.task.id + '"></label>';
                        }
                        str = '<input type="checkbox" class="myCheck" id="c' + row.task.id + '"' + (row.task.reader > 0 ? ' disabled' : '') + ' onclick="checkboxClicked(this)" data-rowId="' + meta.row + '"><label for="c' + row.task.id + '"></label>';
                        return str;
                    }
                    return data;
                }
            },
            {
                "data": 'task.title',
                "render": function (data, type, row, meta) {
                    if (type === "display") {
                        return '<a class="taskListTitle" id="t' + row.task.id + '">' + htmlEncode(data) + '</a>';
                    }
                    return data;
                }
            },
            {
                "data": 'task.completion',
                "width": '120px',
                "render": function (data, type, row, meta) {
                    var realComp;
                    realComp = data > 100 ? 100 : data;
                    if (type === "display") {
                        return '<div class="progress" style="margin-bottom:0;height:16px"><div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="' + realComp + '" aria-valuemin="0" aria-valuemax="100" style="line-height:16px;height:16px;width: ' + realComp + '%;">' + realComp + '%</div></div>';
                    }
                    return realComp;
                }
            },
            {
                "data": 'owner.name',
                "width": '100px'

            },
            {
                "data": 'task.deadLine',
                "width": '120px'
            },
            {
                "visible": false,
                "data": 'task.createTime'
            }
            ],
            "order": [4, 'asc'],
            "oLanguage": {//语言设置  
                "sLengthMenu": "每页显示 _MENU_ 条记录",
                "sZeroRecords": "没有检索到数据",
                "sInfo": "当前显示 _START_ 到 _END_ 条，共 _TOTAL_ 条记录",
                "sInfoEmtpy": "没有数据",
                "sProcessing": '<i class="fa fa-coffee"></i> 正在加载数据...',
                "oPaginate": {
                    "sFirst": "首页",
                    "sPrevious": "<span class=\"fa fa-chevron-left\">",
                    "sNext": "<span class=\"fa fa-chevron-right\">",
                    "sLast": "尾页"
                },
                "sSearch": "搜索 "
            },
            "drawCallback": function (settings) {
                $(".taskListTitle").unbind('click').click(data, function (ev) {
                    var tId = $(this).prop("id").substr(1);
                    showTaskDetail(tId);
                });
            }
        });
    }

    //显示任务详情
    function showTaskDetail(id) {
        $.ajax({ cache: false });
        $("#taskListWrapper").load("parts/taskView.html", function () {
            var task;
            var tId = id;
            var view;

            getTask(tId, true);

            //根据任务id获取详情
            //ifRender，是否立即进行渲染
            function getTask(tId, ifRender) {
                var request = createOperation('getTaskDetail', { id: tId });
                getJson(request, function (data) {
                    task = data.entity;
                    if (ifRender) renderTaskView();
                }, function (status, err) {
                    warn(status + "\n" + err);
                });
            }

            function isReader() {
                if (thisUser.id == task.owner.id) return false;
                if (task.implement != undefined && task.implement != null) {
                    for (var i = 0; i < task.implement.length; i++) {
                        if (thisUser.id == task.implement[i].id) return false;
                    }
                }
                if (task.readers != undefined && task.readers != null) {
                    for (var i = 0; i < task.readers.length; i++) {
                        if (thisUser.id == task.readers[i].id) return true;
                    }
                }
                return true;
            }
            function renderTaskView() {
                var exeUserbook = new userSelector();
                exeUserbook.setData(contacts);
                var rdrUserbook = new userSelector();
                rdrUserbook.setData(contacts);
                progSlider = $("#progSlider").slider({
                    formatter: function (value) {
                        return '进度：' + value + '%';
                    },
                    enabled: !isReader()
                });
                $("#upTaskId").val(task.id);
                if (thisUser.id != task.owner.id) {
                    $("#linkDescrEdit").hide();
                } else {
                    $("#collapseDescr").on("show.bs.collapse", function () {
                        $("#linkDescrEdit").hide();
                        $("#tDescr").hide();
                        $("#tDescrEditor").text(task.description);
                        $("#tDescrEditor").val(task.description);
                    });
                    $("#collapseDescr").on("shown.bs.collapse", function () {
                        $("#tDescrEditor").focus();

                    });
                    $("#btnCancelDescr").click(function () {
                        $("#tDescrEditor").text("");
                        $("#collapseDescr").collapse('hide');
                    });
                    $("#btnSaveDescr").click(function () {
                        saveDescription($("#tDescrEditor").val(), function (data) {
                            if (data.status == 0) {
                                task.description = data.entity.description;
                            }
                            $("#collapseDescr").collapse('hide');
                        })
                    });
                    $("#collapseDescr").on("hide.bs.collapse", function () {
                        $("#tDescrEditor").val("");
                        $("#tDescr").show();
                        showDescription();
                        $("#linkDescrEdit").show();
                    });
                }
                $("#tTitle").html(htmlEncode(task.title));
                showDescription();
                //$("#tCreator").html(task.owner.name);
                $("#tCreator").attr('src', task.owner.avatar);
                $("#tCreator").attr('title', task.owner.name);
                $("#tv-owner-name").html(task.owner.name);

                $("#tv-dd-label").html(new DateConvertor(task.deadLine).toShortDate());
                $("#emerg2").prop("checked", true);
                if (thisUser.id != task.owner.id) {
                    $("#edit-title-btn").hide();
                } else {
                    $("#edit-title-btn").click(function (e) {
                        $("#tTitle").html('<input type="text" id="tTitle-text-editor" style="width:80%;outline:none;border:none">');
                        $("#tTitle-text-editor").val(task.title);
                        $("#tTitle-text-editor").focus();
                        $("#tTitle-text-editor").blur(function () {
                            var tempTitle = $("#tTitle-text-editor").val();
                            if (tempTitle != "" && tempTitle != task.title) {
                                saveTitle(tempTitle, function (data) {
                                    if (data.status == 0) {
                                        task.title = tempTitle;
                                        $("#tTitle").html(htmlEncode(task.title));
                                    }
                                });
                            }
                            $("#tTitle").html(htmlEncode(task.title));
                        });
                        $("#tTitle-text-editor").keyup(function (e) {
                            if (e.which == 13) {
                                var tempTitle = $("#tTitle-text-editor").val();
                                if (tempTitle != "" && tempTitle != task.title) {
                                    saveTitle(tempTitle, function (data) {
                                        if (data.status == 0) {
                                            task.title = tempTitle;
                                            $("#tTitle").html(htmlEncode(task.title));
                                        }
                                    });
                                }
                                $("#tTitle").html(htmlEncode(task.title));
                            }
                        });
                        $('[data-toggle="tooltip"]').tooltip();
                    });
                }

                function showDescription() {
                    if (task.description) {
                        //$("#tDescr").text(htmlEncode(task.description).replace('/\n/g',"<br />"));
                        $("#tDescr").html(htmlEncode(task.description).replace(/\n/g, "<br />"));
                    } else {
                        var str = '<div style="color:#EEEEEE;text-align:center;vertical-align:middle;height:100%"><span class="fa fa-file-text-o fa-3x" aria-hidden="true"></span>您尚未填写任务描述！';
                        $("#tDescr").text(str);
                        $("#tDescr").html(str);
                    }
                }



                renderExecutors();
                renderReaders();
                renderSubTask();
                renderToolbar();
                renderFeedbacks();
                function renderToolbar() {
                    $("#btn-back-to-tasklist").click(function (e) {
                        e.stopPropagation();
                        loadTaskList();
                    });
                    if (isReader()) {
                        $(".task-bar-right").css("visibility", "hidden");
                        return;
                    }

                    //定义删除按键功能
                    if (thisUser.id != task.owner.id) {
                        $("#btn-del-task").hide();
                    } else {
                        $("#btn-del-task").click(function (e) {
                            e.stopPropagation();
                            if (!confirm("您确定要删除任务吗？\n删除任务将连同其子任务一并删除，且无法恢复！"))
                                return;
                            var op = createOperation('delTask', { taskId: task.id });
                            getJsonSync(op, function (data) {

                                if (data.status == 0) {
                                    loadTaskList();
                                }
                                else warn(data.message);
                            }, function (status, err) {
                                warn("请求失败：" + status + "\n错误：" + JSON.stringify(err));
                            });
                        });
                    }
                }

                function renderExecutors() {
                    drawExeList();
                    if (thisUser.id != task.owner.id) {
                        $("#btn-exe-add").hide();
                    } else {
                        $("#addExeDiv").click(function (e) {
                            e.stopPropagation();
                        });
                        $("#btn-exe-add").click(function (e) {
                            e.stopPropagation();
                            $("#addRdrDiv").hide();
                            exeUserbook.setSelectedUsers(getTaskImpUserIds());
                            exeUserbook.setFilteredUsers(getTaskRdrUserIds());
                            exeUserbook.setUserTree('addExeNotebook');
                            exeUserbook.setMultiSelect(true);
                            exeUserbook.onNodeSelected = function (ev, node) {
                                addExecutor(node.id, function (data) {
                                    if (data.status == 0) {
                                        addImpToTask(data.entity);
                                        drawExeList();
                                    } else {
                                        warn(data.message);
                                    }
                                }, function (status, err) {
                                    warn(status + "\n" + err);
                                });
                            }
                            exeUserbook.onNodeUnselected = function (ev, node) {
                                delExecutor(node.id, function (data) {
                                    if (data.status == 0) {
                                        removeImpFromTask(node.id);
                                        drawExeList();
                                    } else {
                                        warn(data.message);
                                    }
                                }, function (status, err) {
                                    warn(status + "\n" + err);
                                });
                            }
                            exeUserbook.show();
                            $("#addExeDiv").show();
                        });
                    }
                }

                function renderReaders() {
                    drawRdrList();
                    if (thisUser.id != task.owner.id) {
                        $("#btn-rdr-add").hide();
                    } else {
                        $("#addRdrDiv").click(function (e) {
                            e.stopPropagation();
                        });
                        $("#btn-rdr-add").click(function (e) {
                            e.stopPropagation();
                            $("#addExeDiv").hide();
                            rdrUserbook.setSelectedUsers(getTaskRdrUserIds());
                            rdrUserbook.setFilteredUsers(getTaskImpUserIds());
                            rdrUserbook.setUserTree('addRdrNotebook');
                            rdrUserbook.setMultiSelect(true);
                            rdrUserbook.onNodeSelected = function (ev, node) {
                                addReader(node.id, function (data) {
                                    if (data.status == 0) {
                                        addRdrToTask(data.entity);
                                        drawRdrList();
                                    } else {
                                        warn(data.message);
                                    }
                                }, function (status, err) {
                                    warn(status + "\n" + err);
                                });
                            }
                            rdrUserbook.onNodeUnselected = function (ev, node) {
                                delReader(node.id, function (data) {
                                    if (data.status == 0) {
                                        removeRdrFromTask(node.id);
                                        drawRdrList();
                                    } else {
                                        warn(data.message);
                                    }
                                }, function (status, err) {
                                    warn(status + "\n" + err);
                                });
                            }
                            rdrUserbook.show();
                            $("#addRdrDiv").show();
                        });
                    }
                }

                function drawRdrList() {
                    var rdrListStr = "";
                    for (var i in task.readers) {
                        if (thisUser.id == task.owner.id)
                            rdrListStr += '<span class="fa fa-close rdrDel" data-del-uid="' + task.readers[i].id + '"></span><span class="fa fa-user taskReader"></span>' + task.readers[i].name;
                        else {
                            rdrListStr += '<span class="fa fa-user taskReader"></span>' + task.readers[i].name;
                        }
                    }
                    $("#readerDiv").html(rdrListStr);
                    if (thisUser.id == task.owner.id) {
                        $(".rdrDel").click(function () {
                            var uid = $(this).data("del-uid");
                            delReader(uid, function (data) {
                                if (data.status == 0) {
                                    removeRdrFromTask(uid);
                                    drawRdrList();
                                } else {
                                    warn(data.message);
                                }
                            }, function (status, err) {
                                warn(status + "\n" + err);
                            });
                        });
                    }
                }
                function drawExeList() {
                    var impListStr = "";
                    for (var i in task.implement) {
                        if (thisUser.id == task.owner.id)
                            impListStr += '<span class="fa fa-close exeDel" data-del-uid="' + task.implement[i].id + '"></span><span class="fa fa-user taskExecutor"></span>' + task.implement[i].name;
                        else
                            impListStr += '<span class="fa fa-user taskExecutor"></span>' + task.implement[i].name;
                    }
                    $("#executorDiv").html(impListStr);
                    if (thisUser.id == task.owner.id) {
                        $(".exeDel").click(function () {
                            var uid = $(this).data("del-uid");
                            delExecutor(uid, function (data) {
                                if (data.status == 0) {
                                    removeImpFromTask(uid);
                                    drawExeList();
                                } else {
                                    warn(data.message);
                                }
                            }, function (status, err) {
                                warn(status + "\n" + err);
                            });
                        });
                    }
                }
                function renderSubTask() {
                    var subtaskStr = "";
                    var newSubTask = new Object();
                    newSubTask.fatherTaskId = task.id;
                    if (!isReader()) {
                        $("#subuserbook").click(function (e) {
                            e.stopPropagation();
                        });
                        us.setUserTree("subuserTreeview");
                        us.onNodeSelected = function (event, node) {
                            $("#subTargetUserName").html(node.text);
                            newSubTask.implementId = node.id;
                            $("#subuserbook").hide();
                        }
                        us.onNodeUnselected = function (event, node) {
                            $("#subTargetUserName").html("");
                            delete newSubTask.implementId;
                            $("#subuserbook").hide();
                        }
                        us.show();
                        $("#subTargetUser").click(function (e) {
                            e.stopPropagation();
                            $("#subuserbook").show();
                        });
                        $("#subTaskDatePicker").datetimepicker({
                            language: 'zh-CN',
                            format: "yyyy-mm-dd",
                            weekStart: 1,
                            todayBtn: 1,
                            autoclose: 1,
                            todayHighlight: 1,
                            startView: 2,
                            minView: 2,
                            forceParse: 0,
                            showMeridian: 1
                        });
                        $("#subTaskDatePicker").on("changeDate", function (ev) {
                            $("#subdateValue").html(new DateConvertor(ev.date).toShortDate());
                        });
                        $("#newSubTaskTitle").keyup(function (e) {
                            if (e.keyCode == 13) {
                                if ($(this).val() == "" || $(this).val() == lastSubTaskTitle) {
                                    return;
                                }

                                newSubTask.title = $(this).val();
                                newSubTask.deadLine = $("#newSubTaskDate").val();
                                getJson(createOperation('createTask', newSubTask), function (data) {
                                    if (data.status == 0) {
                                        data.entity.task.owner = data.entity.owner;
                                        appendSubTask(data.entity.task, true);
                                        lastSubTaskTitle = data.entity.task.title;
                                        $("#newSubTaskTitle").val("");
                                    }
                                    else warn(data.message);
                                }, function (status, err) {
                                    warn("REQ STAT=" + status + "\nERR:" + err);
                                });
                            }
                        });
                    }
                    else {
                        $(".quickaddbox").hide();
                    }
                    showSubTasks();
                }

                function renderFeedbacks() {
                    getJson(createOperation('getFeedBack', { taskId: task.id }), function (data) {
                        if (data.status == 0) {
                            var fbs = data.entity;
                            var str = "";
                            for (var i = 0; i < fbs.length; i++) {
                                str += '<div class="col-xs-12 feedback-item">'
                                    + '<div class="fb-item-avatar pull-left">'
                                    + '<img class="img-circle avatar-md" src="' + fbs[i].feedBackUser.avatar + '">'
                                    + '</div><div class="feedback-props">'
                                    + '<span class="feedback-name">' + fbs[i].feedBackUser.name + '</span>'
                                    + '<span class="feedback-time">' + (new DateConvertor(fbs[i].feedBack.responseTime)).toShortDateTime() + '</span>'
                                    + '<a href="javavscript:delFeedback(' + fbs[i].feedBack.id + ')" class="pull-right"><span class="fa fa-trash-o" aria-hidden="true"></span></a>'
                                    + '<div>' + text2HTML(fbs[i].feedBack.response) + '</div></div></div>';
                            }
                            $(".task-feedback-box").html(str);
                        } else {
                            warn(data.message);
                        }
                    });
                    $("#feedText").unbind("keyup").keyup(function (e) {
                        if (e.ctrlKey && e.keyCode == 13) {
                            sendFeedback();
                            console.log("send keyup");
                        }
                    });
                    $("#feedSendBtn").unbind("click").click(function () {
                        sendFeedback();
                        console.log("send btn");
                    });
                }



                function appendSubTask(subTask, attachClick) {
                    var str = '<div class="subtask-wrapper" data-tid="' + subTask.id + '">'
                        + '<div class="qbox-shrink qbox-nogrow subtask-title">' + subTask.title + '</div>'
                        + '<div class="qbox-fix subtask-toolbox"><span class="fa fa-trash-o meta-btn del-subtask-btn" data-tid="' + subTask.id + '" aria-hidden="true"> </div>'
                        + '<div class="qbox-shrink"></div>'
                        + '<div class="subtask-progress qbox-fix"><div class="progress" style="margin-bottom:0;height:16px"><div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="' + (subTask.completion > 100 ? 100 : subTask.completion) + '" aria-valuemin="0" aria-valuemax="100" style="line-height:16px;height:16px;width: ' + (subTask.completion > 100 ? 100 : subTask.completion) + '%;">' + (subTask.completion > 100 ? 100 : subTask.completion) + '%</div></div></div>'
                        + '<div class="subtask-deadline qbox-fix">' + (new DateConvertor(subTask.deadLine).toShortDate()) + '</div>'
                        + '<div class="subtask-owner qbox-fix">' + subTask.owner.name + '</div></div>'
                    $(".subtask-list").append(str);
                    if (attachClick) {
                        $(".subtask-wrapper").unbind('click').click(function (e) {
                            e.stopPropagation();
                            showTaskDetail($(this).data('tid'));
                        });
                    }
                }
                function showSubTasks() {
                    for (var i = 0; i < task.subTaskList.length; i++) {
                        appendSubTask(task.subTaskList[i]);
                    }
                    $(".subtask-wrapper").unbind('click').click(function (e) {
                        e.stopPropagation();
                        showTaskDetail($(this).data('tid'));
                    });
                }

                //标题旁边的完成checkbox状态切换事件
                if (isReader()) {
                    $('label[for="chkCompletion"]').css("visibility", "hidden");
                } else {
                    $("#chkCompletion").change(function (e) {
                        if ($(this).prop("checked")) {
                            setCompletion(task.id, 1000, function (data) {
                                if (data.status == 0) {
                                    task.completion = data.entity.completion;
                                    progSlider.slider('setValue', task.completion > 100 ? 100 : task.completion, false, false);
                                }
                                else {
                                    $(this).prop("checked", !$(this).prop("checked"));
                                    warn(data.message)
                                };
                            }, function (status, err) {
                                $(this).prop("checked", !$(this).prop("checked"));
                                warn(status + "\n" + err);
                            });
                        } else {
                            setCompletion(task.id, -1, function (data) {
                                if (data.status == 0) {
                                    task.completion = data.entity.completion;
                                    progSlider.slider('setValue', task.completion > 100 ? 100 : task.completion, false, false);
                                }
                                else {
                                    $(this).prop("checked", !$(this).prop("checked"));
                                    warn(data.message)
                                };
                            });
                        }
                    });
                }

                //设置任务完成度的进度条初始值和改变后的事件
                progSlider.slider('setValue', task.completion > 100 ? 100 : task.completion, false, false);
                if (task.completion >= 100) $("#chkCompletion").prop('checked', true);
                progSlider.on("slideStop", function (ev) {
                    setCompletion(tId, ev.value, function (data) {
                        if (data.status == 0) {
                            task.completion = data.entity.completion;
                            if (task.completion >= 100)
                                $("#chkCompletion").prop('checked', true);
                            else
                                $("#chkCompletion").prop('checked', false);
                        } else {
                            progSlider.slider('setValue', task.completion > 100 ? 100 : task.completion, false, false);
                            warn(data.message);
                        }
                    });
                });
            }

            function saveTitle(title, callback, errCallback) {
                //callback({status:0});
                var op = createOperation('setTaskTitle', { taskId: task.id, title: title });
                getJson(op, callback, errCallback);
            }
            function saveDescription(text, callback, errCallback) {
                //callback({ status: 0 });
                var op = createOperation('setTaskDesc', { taskId: task.id, description: text });
                getJson(op, callback, errCallback);
            }
            function setEmergency(value, callback, errCallback) {
                var op = createOperation('setEmergency', { taskId: task.id, emergency: value });
                getJson(op, callback, errCallback);
            }
            function delExecutor(uid, callback, errCallback) {
                //callback({ status: 0 });
                var op = createOperation('setTaskImp', { taskId: task.id, action: 0, userId: uid });
                getJson(op, callback, errCallback);
            }
            function delReader(uid, callback, errCallback) {
                //callback({ status: 0 });
                var op = createOperation('setTaskReaders', { taskId: task.id, action: 0, userId: uid });
                getJson(op, callback, errCallback);
            }
            function addExecutor(uid, callback, errCallback) {
                //callback({ status: 0 });
                var op = createOperation('setTaskImp', { taskId: task.id, action: 1, userId: uid });
                getJson(op, callback, errCallback);
            }
            function addReader(uid, callback, errCallback) {
                //callback({ status: 0 });
                var op = createOperation('setTaskReaders', { taskId: task.id, action: 1, userId: uid });
                getJson(op, callback, errCallback);
            }
            function removeImpFromTask(uid) {
                for (var i = 0; i < task.implement.length; i++) {
                    if (uid == task.implement[i].id) {
                        task.implement.splice(i, 1);
                        return;
                    }
                }
            }
            function removeRdrFromTask(uid) {
                for (var i = 0; i < task.readers.length; i++) {
                    if (uid == task.readers[i].id) {
                        task.readers.splice(i, 1);
                        return;
                    }
                }
            }
            function addImpToTask(u) {
                if (task.implement == undefined) task.implement = new Array();
                task.implement.push(u);
            }
            function addRdrToTask(u) {
                if (task.readers == undefined) task.readers = new Array();
                task.readers.push(u);
            }
            function getTaskImpUserIds() {
                var ids = new Array();
                if (!task.implement) return ids;
                for (var i = 0; i < task.implement.length; i++) {
                    ids.push(task.implement[i].id);
                }
                return ids;
            }
            function getTaskRdrUserIds() {
                var ids = new Array();
                if (!task.readers) return ids;
                for (var i = 0; i < task.readers.length; i++) {
                    ids.push(task.readers[i].id);
                }
                return ids;
            }

            function appendFeedback(fb) {
                var str = "";
                str += '<div class="col-xs-12 feedback-item">'
                    + '<div class="fb-item-avatar pull-left">'
                    + '<img class="img-circle avatar-md" src="' + fb.feedBackUser.avatar + '">'
                    + '</div><div class="feedback-props">'
                    + '<span class="feedback-name">' + fb.feedBackUser.name + '</span>'
                    + '<span class="feedback-time">' + (new DateConvertor(fb.feedBack.responseTime)).toShortDateTime() + '</span>'
                    + '<a href="javascript:delFeedback(' + fb.feedBack.id + ')" class="pull-right"><span class="fa fa-trash-o" aria-hidden="true"></span></a>'
                    + '<div>' + text2HTML(fb.feedBack.response) + '</div></div></div>';
                $(".task-feedback-box").append(str);
            }

            function sendFeedback() {
                var text = $("#feedText").val().trim();
                if (!text) return;
                if (text == lastFeedback) return;
                getJson(createOperation('setFeedback', { action: 1, taskId: task.id, feedBack: text }), function (data) {
                    if (data.status == 0) {
                        lastFeedback = data.entity.feedBack.response;
                        $("#feedText").val("");
                        appendFeedback(data.entity);
                    }
                }, function (status, err) {
                    warn(status + "\n" + err.toString());
                });
            }

        });
    }

});
